import _region as reg
import parser as RP

import jjregion.image
import jjregion.wcs


class RegionFactory(RP.RegionFactoryDelegatedCreateShape, RP.RegionFactoryOpObject):

    def _check_param(self, shapename, format, param):
        param_length = len(format.split())
        if len(param) != param_length:
            raise self.IncorrectShape("%s require (%s",
                                      (shapename, ", ".join(format.split())))
        
    def shape_circle(self, number_list):
        self._check_param("circle", "coord coord distance", number_list)
        return reg.Circle(*number_list)

    def shape_polygon(self, number_list):
        if len(number_list) % 2 != 0:
            raise self.IncorrectShape("%s require even number of coords.")
            
        return reg.Polygon(number_list[::2], number_list[1::2])

    def shape_ellipse(self, number_list):
        self._check_param("ellipse", "coord coord distance, distance, angle", number_list)
        r =  reg.Ellipse(*number_list[:-1])
        return reg.Rotated(r, number_list[-1], *number_list[:2])
        
    def shape_rotbox(self, number_list):
        self._check_param("rotbox", "coord coord distance distance angle", number_list)
        r =  reg.Box(*number_list[:-1])
        return reg.Rotated(r, number_list[-1], *number_list[:2])


    shape_box = shape_rotbox


    def convert_number(self, s, l, t):
        if len(t) == 1:
            return float(t[0])
        elif t[-1] in ["'",'"']:
            return spherical_angle(t[0])
        else:
            return sexagecimal(t[0])


class sexagecimal(object):
    def __init__(self, s):
        if s[0] == "-":
            _sign = -1
            s=s[1:]
        else:
            _sign = 1

        ss = map(float, s.split(":"))
        if len(ss) == 1:
            v = _sign * ss[0]
        elif len(ss) == 2:
            v = _sign * (ss[0] + ss[1]/60.)
        elif len(ss) == 3:
            v = _sign * (ss[0] + ss[1]/60. + ss[2]/3600.)

        self.degree = v




class WcsCoord(object):

    @staticmethod
    def value(s):
        if s[0] == "-":
            _sign = -1
            s=s[1:]
        else:
            _sign = 1

        ss = map(float, s.split(":"))
        if len(ss) == 1:
            v = _sign * ss[0]
        elif len(ss) == 2:
            v = _sign * (ss[0] + ss[1]/60.)
        elif len(ss) == 3:
            v = _sign * (ss[0] + ss[1]/60. + ss[2]/3600.)

        return v



class WcsAng(object):

    @staticmethod
    def check(s):
        if s.strip()[-1] in ["'",'"']:
            return True
        else:
            return False


    @staticmethod
    def value(s):
        s = s.strip()
        #degree = []
        degree = 0.
        
        ind = s.find("'")
        if ind > 1: # arcminute
            degree += (float(s[:ind])/60.)
            s = s[ind+1:]

        ind = s.find("\"")
        if ind > 1: # arcsec
            degree += (float(s[:ind])/3600.)
            s = s[ind+1:]

        #super(spherical_angle, self).__init__(degree)
        if s:
            raise Exception("wrong format")
        else:
            return degree
        
    





        
class RegionFactoryDs9(RP.RegionFactoryOpObject):
    #def __init__(self, image_factory):
    #    self.image_factory = image_factory


    def check_param(self, shapename, param):
        shape_type, number_list =_format[shapename](param)
        return shape_type, number_list

    def create_shape(self, shape_name, number_list):

        shape_type, number_list = self.check_param(shape_name, number_list)
        
        r = self.image_factory.create_shape(shape_name, number_list)

        if shape_type == "wcs":
            r = self.wcs_factory.create_shape(shape_name, number_list)
        elif shape_type == "image":
            r = self.image_factory.create_shape(shape_name, number_list)
        else:
            raise Exception("")
        
        return r
    
    @arg_wcs(WcsCoordOdd, WcsCoordEven, WcsAng)
    def shape_circle(self, *number_list):
        return reg.Circle(*number_list)

    @wcs_shape_repeat(WcsCoordOdd, WcsCoordEven)
    def shape_polygon(self, number_list):
        if len(number_list) % 2 != 0:
            raise self.IncorrectShape("%s require even number of coords.")
            
        return reg.Polygon(number_list[::2], number_list[1::2])

    @arg_wcs(WcsCoordOdd, WcsCoordEven, WcsAng, WcsAng)
    def shape_ellipse(self, number_list):
        self._check_param("ellipse", "coord coord distance, distance, angle", number_list)
        r =  reg.Ellipse(*number_list[:-1])
        return reg.Rotated(r, number_list[-1], *number_list[:2])

    @arg_wcs(WcsCoordOdd, WcsCoordEven, WcsAng, WcsAng)        
    def shape_rotbox(self, number_list):
        self._check_param("rotbox", "coord coord distance distance angle", number_list)
        r =  reg.Box(*number_list[:-1])
        return reg.Rotated(r, number_list[-1], *number_list[:2])


    shape_box = shape_rotbox




